// package: learn-go
// filename: nginxlog
// author: diogoxiang@gmail.com
// time: 2023/12/11 15:45

package nginxlog

import (
	"bufio"
	"fmt"
	"os"
	"regexp"
	"strings"
)

// LogEntry 表示一个日志条目
type LogEntry struct {
	RemoteAddr    string
	RemoteUser    string
	TimeLocal     string
	Request       string
	Status        string
	BodyBytesSent string
	HttpReferer   string
	UserAgent     string
	XForwardedFor string
}

// ParseLine 解析单行日志
func ParseLine(line string) (*LogEntry, error) {
	pattern := `(\S+) - (\S+) \[([\w:/]+\s[+\-]\d{4})\] "([^"]*)" (\d{3}) (\d+) "([^"]*)" "([^"]*)" "([^"]*)"`
	r := regexp.MustCompile(pattern)
	matches := r.FindStringSubmatch(line)

	if len(matches) < 10 {
		return nil, fmt.Errorf("invalid log line")
	}

	return &LogEntry{
		RemoteAddr:    matches[1],
		RemoteUser:    matches[2],
		TimeLocal:     matches[3],
		Request:       matches[4],
		Status:        matches[5],
		BodyBytesSent: matches[6],
		HttpReferer:   matches[7],
		UserAgent:     matches[8],
		XForwardedFor: matches[9],
	}, nil
}

// ParseFile 解析日志文件
func ParseFile(filePath string) ([]*LogEntry, error) {
	file, err := os.Open(filePath)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	var entries []*LogEntry
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		entry, err := ParseLine(scanner.Text())
		if err != nil {
			continue // 或者处理错误
		}
		entries = append(entries, entry)
	}

	return entries, scanner.Err()
}

func extractURL(request string) string {
	parts := strings.Split(request, " ")
	if len(parts) > 1 {
		return parts[1] // 返回 URL 部分
	}
	return ""
}

func CountURLs(entries []*LogEntry) map[string]int {
	urlCounts := make(map[string]int)
	for _, entry := range entries {
		url := extractURL(entry.Request)
		urlCounts[url]++
	}
	return urlCounts
}
